import Evt from './events'
type Listener = (...a:any[])=>void
const evt = new Evt()
export default class MatchMedia{
    private mediaListener:(...a:any[])=>void;
    private media:MediaQueryList;
    private match:boolean
    get matched(){return this.match}
    constructor(mediaKey:string){
        const mediaListener = (e:MediaQueryList|MediaQueryListEvent)=>{
            this.match = e.matches
            evt.emit(mediaKey,e.matches)
        }
        const media = window.matchMedia(mediaKey);
        if(media.addEventListener)
            media.addEventListener("change",mediaListener)
        else if(media.addListener)
            media.addListener(mediaListener)
        
        mediaListener(media)

        this.mediaListener = mediaListener
        this.media = media
        this.match = media.matches
        MatchMedia.instances.set(mediaKey,this)
    }
    off(){
        const media = this.media
        if(media.removeEventListener)
            media.removeEventListener("change",this.mediaListener)
        else if(media.removeListener)
            media.removeListener(mediaListener)
    }
    static instances = new Map<string,MatchMedia>();
    static maxWidth(width:string,mediaListener:Listener){
        MatchMedia.on('max-width',width,mediaListener)
    }
    static minWidth(width:string,mediaListener:Listener){
        MatchMedia.on("min-width",width,mediaListener)
    }
    static on(k:string,v:string,mediaListener:Listener){
        const mediaKey = `(${k}: ${v})`;
        evt.on(mediaKey,mediaListener)
        if(MatchMedia.has(mediaKey))
            mediaListener(MatchMedia.get(mediaKey).matched)
        else
            new MatchMedia(mediaKey)
    }
    static offMaxWidth(width:string,mediaListener?:Listener){
        MatchMedia.off('max-width',width,mediaListener)
    }
    static offMinWidth(width:string,mediaListener?:Listener){
        MatchMedia.off("min-width",width,mediaListener)
    }
    static off(k:string,v:string,mediaListener?:Listener){
        const mediaKey = `(${k}: ${v})`;
        evt.off(mediaKey,mediaListener)
        if(!mediaListener){
            const mm = MatchMedia.get(mediaKey)
            mm&&mm.off()
            MatchMedia.instances.delete(mediaKey)
        }
    }
    static has(mediaKey:string){
        return MatchMedia.instances.has(mediaKey)
    }
    static get(mediaKey:string){
        return MatchMedia.instances.get(mediaKey)
    }
}